/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "test_mctp_class.h"
#include <mctp/mctp.h>
#include <thread>
#include <chrono>
#include <gtest/gtest.h>

namespace test_mctp {

class test_object : public mc::engine::object<test_object> {
public:
    MC_OBJECT(test_object, "TestObject", "/bmc/kepler/Systems/1/TestObject")

    test_object() = default;
};

class mctp_test : public ::testing::Test {
protected:
    void SetUp() override {
        // 每个测试使用独立的service实例
        m_test_service = mc::make_shared<test_service>();
        m_test_service->init();
        m_test_service->start();

        // 创建 test_object（必须由 shared_ptr 管理，因为 register_object 需要）
        m_test_object = mc::make_shared<test_mctp::test_object>();
        m_test_object->set_object_name("TestObject");
        m_test_object->set_object_path("/bmc/kepler/Systems/1/TestObject");

        // 注册 test_object 到 service（这会自动设置 service）
        m_test_service->register_object(*m_test_object);
    }
    void TearDown() override {
        // 清理 test_object
        if (m_test_object) {
            try {
                m_test_service->unregister_object(m_test_object);
            } catch (...) {
                // 忽略注销失败的情况
            }
            m_test_object.reset();
        }

        // 停止服务
        if (m_test_service) {
            m_test_service->stop();
            m_test_service.reset();
        }
    }

    mc::shared_ptr<test_mctp::test_object> m_test_object;
    mc::shared_ptr<test_service> m_test_service;
};


// 测试 init_phy_addr 静态方法 - 正常情况
TEST_F(mctp_test, init_phy_addr_normal) {
    uint8_t  bus      = 0x01;
    uint8_t  device   = 0x02;
    uint8_t  function = 0x03;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    // 验证结果：bus(0xFF) | (device(0x1F) << 11) | (function(0x07) << 8)
    uint16_t expected = (bus & 0xFF) | ((device & 0x1F) << 11) | ((function & 0x07) << 8);
    EXPECT_EQ(result, expected);
}

// 测试 init_phy_addr 静态方法 - 边界值：bus 最大值
TEST_F(mctp_test, init_phy_addr_bus_max) {
    uint8_t  bus      = 0xFF;
    uint8_t  device   = 0x00;
    uint8_t  function = 0x00;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    EXPECT_EQ(result, static_cast<uint16_t>(0x00FF));
}

// 测试 init_phy_addr 静态方法 - 边界值：device 最大值
TEST_F(mctp_test, init_phy_addr_device_max) {
    uint8_t  bus      = 0x00;
    uint8_t  device   = 0x1F;
    uint8_t  function = 0x00;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    EXPECT_EQ(result, static_cast<uint16_t>(0x1F << 11));
}

// 测试 init_phy_addr 静态方法 - 边界值：function 最大值
TEST_F(mctp_test, init_phy_addr_function_max) {
    uint8_t  bus      = 0x00;
    uint8_t  device   = 0x00;
    uint8_t  function = 0x07;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    EXPECT_EQ(result, static_cast<uint16_t>(0x07 << 8));
}

// 测试 init_phy_addr 静态方法 - 边界值：所有值都为 0
TEST_F(mctp_test, init_phy_addr_all_zero) {
    uint8_t  bus      = 0x00;
    uint8_t  device   = 0x00;
    uint8_t  function = 0x00;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    EXPECT_EQ(result, static_cast<uint16_t>(0x0000));
}

// 测试 init_phy_addr 静态方法 - 边界值：所有值都为最大值
TEST_F(mctp_test, init_phy_addr_all_max) {
    uint8_t  bus      = 0xFF;
    uint8_t  device   = 0x1F;
    uint8_t  function = 0x07;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    uint16_t expected = (0xFF & 0xFF) | ((0x1F & 0x1F) << 11) | ((0x07 & 0x07) << 8);
    EXPECT_EQ(result, expected);
}

// 测试 init_phy_addr 静态方法 - device 超过最大值，应该被截断
TEST_F(mctp_test, init_phy_addr_device_overflow) {
    uint8_t  bus      = 0x00;
    uint8_t  device   = 0xFF; // 超过 0x1F，应该被截断为 0x1F
    uint8_t  function = 0x00;
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    uint16_t expected = ((0xFF & 0x1F) << 11);
    EXPECT_EQ(result, expected);
}

// 测试 init_phy_addr 静态方法 - function 超过最大值，应该被截断
TEST_F(mctp_test, init_phy_addr_function_overflow) {
    uint8_t  bus      = 0x00;
    uint8_t  device   = 0x00;
    uint8_t  function = 0xFF; // 超过 0x07，应该被截断为 0x07
    uint16_t result   = dev::mctp::init_phy_addr(bus, device, function);

    uint16_t expected = ((0xFF & 0x07) << 8);
    EXPECT_EQ(result, expected);
}

// 测试构造函数 - 带 position
TEST_F(mctp_test, constructor_with_position) {
    uint16_t                    phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE      msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string                 position = "0101";
    mc::shared_ptr<dev::mctp> mctp_obj =
        mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    EXPECT_NE(mctp_obj, nullptr);
    // 立即清理，避免在Teardown时出现问题
    mctp_obj.reset();
}

// 测试构造函数 - 不带 position（空字符串）
TEST_F(mctp_test, constructor_without_position) {
    uint16_t               phy_addr = 0x0202;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_PLDM;
    std::string            position = "";
    mc::shared_ptr<dev::mctp> mctp_obj =
        mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    EXPECT_NE(mctp_obj, nullptr);
    // 立即清理，避免在Teardown时出现问题
    mctp_obj.reset();
}

// 测试构造函数 - 不同的 MESSAGE_TYPE
TEST_F(mctp_test, constructor_different_message_types) {
    uint16_t phy_addr = 0x0303;
    std::string position = "0303";

    // 测试所有消息类型
    std::vector<dev::MCTP_MESSAGE_TYPE> msg_types = {
        dev::MCTP_MESSAGE_TYPE_MCTP_CTRL, dev::MCTP_MESSAGE_TYPE_PLDM,
        dev::MCTP_MESSAGE_TYPE_NCSI,      dev::MCTP_MESSAGE_TYPE_ETHERNET,
        dev::MCTP_MESSAGE_TYPE_NVME,      dev::MCTP_MESSAGE_TYPE_SPDM,
        dev::MCTP_MESSAGE_TYPE_SECUREDMSG, dev::MCTP_MESSAGE_TYPE_VDPCI,
        dev::MCTP_MESSAGE_TYPE_VDIANA};

    for (auto msg_type : msg_types) {
        mc::shared_ptr<dev::mctp> mctp_obj =
            mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);
        EXPECT_NE(mctp_obj, nullptr);
        // 立即清理，避免在Teardown时出现问题
        mctp_obj.reset();
    }
}

// 测试构造函数 - 边界值：phy_addr 为 0
TEST_F(mctp_test, constructor_phy_addr_zero) {
    uint16_t               phy_addr = 0x0000;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0000";
    mc::shared_ptr<dev::mctp> mctp_obj =
        mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    EXPECT_NE(mctp_obj, nullptr);
    // 立即清理，避免在Teardown时出现问题
    mctp_obj.reset();
}

// 测试构造函数 - 边界值：phy_addr 为最大值
TEST_F(mctp_test, constructor_phy_addr_max) {
    uint16_t               phy_addr = 0xFFFF;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "FFFF";
    mc::shared_ptr<dev::mctp> mctp_obj =
        mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    EXPECT_NE(mctp_obj, nullptr);
    // 立即清理，避免在Teardown时出现问题
    mctp_obj.reset();
}

// 测试 request 方法 - create_endpoint_success 为 false 时应该返回 false
TEST_F(mctp_test, request_endpoint_not_created) {
    uint16_t               phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0101";
    auto test_mctp = mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    mc::dict             ctx;
    std::vector<uint8_t> data = {0x01, 0x02, 0x03};
    int32_t              timeout_ms = 1000;
    std::string          rsp;

    // 由于 create_endpoint_success 默认为 false，应该返回 false
    bool result = test_mctp->request(ctx, data, timeout_ms, rsp);
    EXPECT_FALSE(result);
}

// 测试 create_transport_obj 方法 - 正常情况
TEST_F(mctp_test, DISABLED_create_transport_obj_normal) {
    // 这个测试被禁用，因为transport_obj的生命周期管理有问题
    // TODO: 修复transport_obj的创建和清理逻辑

    uint16_t               phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0101";
    auto test_mctp = mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);
    ASSERT_NE(test_mctp, nullptr) << "Failed to create mctp object";

    mc::dict transport_interface = {
        {"ServiceName", "TestService"},
        {"TargetEid", static_cast<uint8_t>(5)},
        {"TargetPhyAddr", phy_addr},
        {"MessageType", static_cast<uint8_t>(msg_type)},
    };
    mc::dict transport_object = {
        {"bmc.kepler.Systems.Mctp.PCIeTransport", transport_interface},
    };

    // 应该不抛出异常
    EXPECT_NO_THROW(test_mctp->create_transport_obj(transport_object));
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    // 立即清理
    test_mctp.reset();
}

// 测试 create_transport_obj 方法 - 多次调用（测试重复注册）
TEST_F(mctp_test, DISABLED_create_transport_obj_multiple_times) {
    uint16_t               phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0101";
    auto test_mctp = mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    mc::dict transport_interface = {
        {"ServiceName", "TestService"},
        {"TargetEid", static_cast<uint8_t>(5)},
        {"TargetPhyAddr", phy_addr},
        {"MessageType", static_cast<uint8_t>(msg_type)},
    };
    mc::dict transport_object = {
        {"bmc.kepler.Systems.Mctp.PCIeTransport", transport_interface},
    };

    // 第一次调用
    EXPECT_NO_THROW(test_mctp->create_transport_obj(transport_object));

    // 第二次调用（应该处理重复注册的情况）
    EXPECT_NO_THROW(test_mctp->create_transport_obj(transport_object));

    // 立即清理
    test_mctp.reset();
}

// 测试 create_transport_and_endpoint 方法 - 正常情况
TEST_F(mctp_test, DISABLED_create_transport_and_endpoint_normal) {
    uint16_t               phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0101";
    auto test_mctp = mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    std::string module_name = "TestModule";
    bool        callback_called = false;

    std::function<void()> cb = [&callback_called]() { callback_called = true; };

    // 应该不抛出异常
    EXPECT_NO_THROW(test_mctp->create_transport_and_endpoint(module_name, cb));

    // 注意：由于 try_get_endpoint_object 是异步的，回调可能不会立即执行
    // 这里主要测试方法调用不会崩溃

    // 等待异步操作完成
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    // 立即清理
    test_mctp.reset();
}

// 测试 create_transport_and_endpoint 方法 - 空 module_name
TEST_F(mctp_test, DISABLED_create_transport_and_endpoint_empty_module_name) {
    uint16_t               phy_addr = 0x0101;
    dev::MCTP_MESSAGE_TYPE msg_type = dev::MCTP_MESSAGE_TYPE_NCSI;
    std::string            position = "0101";
    auto test_mctp = mc::make_shared<dev::mctp>(m_test_object.get(), phy_addr, msg_type, position);

    std::string module_name = "";
    bool        callback_called = false;

    std::function<void()> cb = [&callback_called]() { callback_called = true; };

    // 应该不抛出异常
    EXPECT_NO_THROW(test_mctp->create_transport_and_endpoint(module_name, cb));

    // 等待异步操作完成
    std::this_thread::sleep_for(std::chrono::milliseconds(200));

    // 立即清理
    test_mctp.reset();
}

} // namespace test_mctp

// 添加反射元数据定义（必须在命名空间外）
MC_REFLECT(test_mctp::test_object)

